import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectModel } from '@nestjs/sequelize';
import { randomUUID } from 'crypto';
import { Op } from 'sequelize';
import { WhereOptions } from 'sequelize/types';
import { Attributes, CountWithOptions } from 'sequelize/types/model';
import { Model } from 'sequelize-typescript';

import { FileCollectionModel } from '@/models/file_collection.model';
import { Submitter } from '@/models/submitter.model';
import { XmwUser } from '@/models/xmw_user.model';
import { ListFileCollectionDto } from '@/modules/administrative/file-collection/dto';
import { CreateFileCollectionDto } from '@/modules/administrative/file-collection/dto/create-file_collection.dto';
import { UpdateFileCollectionDto } from '@/modules/administrative/file-collection/dto/update-file_collection.dto';
import { responseMessage } from '@/utils';
import { Logger } from '@/utils/log4js';
import type { SessionTypes } from '@/utils/types';

@Injectable()
export class FileCollectionService {
  constructor(
    // 使用 InjectModel 注入参数，注册数据库实体
    @InjectModel(FileCollectionModel)
    private readonly fileCollectionModel: typeof FileCollectionModel,
    private readonly jwtService: JwtService,
    @InjectModel(Submitter)
    private readonly submitterModel: typeof Submitter,
    @InjectModel(XmwUser)
    private readonly userModel: typeof XmwUser,
  ) {}

  /**
   * 创建任务
   * @param createFileCollectionDto
   * @param session
   * @param token
   */
  async create(
    createFileCollectionDto: CreateFileCollectionDto,
    session: SessionTypes,
    token?: string,
  ) {
    // 获取当前登录用户 id
    const { user_id: uid } = this.jwtService.decode(token.split(' ').pop());
    // 目前存在bug，获取不到用户信息
    const user_id = session?.currentUserInfo?.user_id ?? uid;
    const [result, created] = await this.fileCollectionModel.findOrCreate({
      where: {
        [Op.or]: {
          task_id: createFileCollectionDto.task_id ?? randomUUID(),
          title: createFileCollectionDto.title,
        },
      },
      defaults: {
        ...createFileCollectionDto,
        founder_id: user_id ?? 'bf75a509-f90e-4a29-8bf7-470b581550f6',
      },
    });
    const { task_id } = result;
    const { access, submitter } = createFileCollectionDto;
    // 提交人不为空时，插入提交人信息
    if (access === 'some' && created) {
      const users = await this.userModel.findAll({
        where: {
          user_id: submitter,
        },
      });
      const submitter_ids = users.map((item) => ({
        user_id: item.user_id,
        user_name: item.user_name,
        task_id,
      }));
      const s = await this.submitterModel.bulkCreate(submitter_ids);
      if (s.length === 0) {
        Logger.error(
          `用户 ${user_id} 创建了任务 ${createFileCollectionDto.title}，但创建关联失败失败`,
        );
        return responseMessage({}, '数据有误', 400);
      }
    }
    if (!created) {
      return responseMessage({}, '该任务已存在或任务名重复', 400);
    }
    Logger.info(`用户 ${user_id} 创建了任务 ${createFileCollectionDto.title}`);
    return responseMessage(result);
  }

  /**
   * 查询任务列表
   * @param fileCollectionList
   * @param token
   */
  async findAll(fileCollectionList: ListFileCollectionDto, token: string) {
    // 获取token用户id
    const { user_id } = this.jwtService.decode(token.split(' ').pop());
    // 解构参数
    const { title, file_type, pinned, current = 1, pageSize = 10 } = fileCollectionList;
    // 拼接查询参数
    const where: WhereOptions = {
      founder_id: user_id,
    };
    if (title) where.title = { [Op.substring]: title };
    if (file_type) where.file_type = { [Op.substring]: file_type };
    if (pinned) where.pinned = { [Op.eq]: pinned };
    // 查询总数
    const total = await this.fileCollectionModel.count({ where });
    // 分页查询数据
    const list = await this.fileCollectionModel.findAll({
      where,
      // 联表查询
      // include: [
      //   {
      //     model: XmwUser,
      //     as: 'u',
      //     attributes: ['user_id', 'user_name'],
      //     where: {
      //       user_id,
      //     },
      //   },
      // ],
      // 排序
      order: [['created_time', 'DESC']],
      // 分页
      offset: (fileCollectionList.current - 1) * fileCollectionList.pageSize,
    });
    return responseMessage({ list, total, current, pageSize });
  }

  /**
   * 查询任务列表
   * @param fileCollectionList
   */
  async findAllTask(fileCollectionList: ListFileCollectionDto) {
    // 解构参数
    const { title, file_type, pinned } = fileCollectionList;
    const { current = 1, pageSize = 10 } = fileCollectionList;
    // 拼接查询参数
    const where: WhereOptions = {};
    if (title) where.title = { [Op.substring]: title };
    if (file_type) where.file_type = { [Op.substring]: file_type };
    if (pinned) where.pinned = { [Op.eq]: pinned };
    // 查询总数
    const total = await this.fileCollectionModel.count({ where } as CountWithOptions<
      Attributes<Model>
    >);
    // 分页查询数据
    const list = await this.fileCollectionModel.findAll({
      where,
      // 排序
      order: [['created_time', 'DESC']],
      // 分页
      offset: (Number(current) - 1) * pageSize,
      limit: Number(pageSize),
    });
    const founder_ids = list.map((item) => item.founder_id);
    const users = await this.userModel.findAll({
      where: {
        user_id: founder_ids,
      },
    });

    return responseMessage({
      list: list.map((item) => ({
        ...item.dataValues,
        access_pwd: null,
        founder_name: users.find((user) => user.user_id === item.founder_id)?.user_name,
      })),
      total,
      current,
      pageSize,
    });
  }

  /**
   * 查询单个任务
   * @param id
   */
  async findOne(id: string) {
    const where: WhereOptions = {
      task_id: id,
    };
    const result = await this.fileCollectionModel.findOne({ where });
    const submitter = await this.submitterModel.findAll({
      where: {
        task_id: id,
      },
    });
    delete result.dataValues.submitter;
    const submitted_number = submitter.filter((item) => !!item.file_path).length;
    const total_number = submitter.length;
    return responseMessage({
      ...result.dataValues,
      submit: { submitter, submitted_number, total_number },
    });
  }

  update(id: number, updateFileCollectionDto: UpdateFileCollectionDto) {
    return `This action updates a #${id} fileCollection`;
  }

  async remove(ids: string[]) {
    const result = await this.fileCollectionModel.destroy({ where: { task_id: ids } });
    if (result === 0) {
      return responseMessage(result, '删除失败', 400);
    }
    return responseMessage(result);
  }
}
